﻿#include "Snake_Game.h"

//------------------------------- Snake_Game ----------------------------------
// 게임에 필요한 뱀, 맵에 메모리를 할당하고 값들을 초기화 해준다.
//-----------------------------------------------------------------------------
Snake_Game::Snake_Game() : speed_ (150) , kMaxItemPosHeigh(17), kMaxItemPosWidth(75) , current_stage_(STAGE_ONE) , life_(5) , goal_item_num_()
{
};

//------------------------------- SetGame -------------------------------------
// 게임을 처음 시작했을때 스테이지를 고를 수 있도록 해준다.
//-----------------------------------------------------------------------------
void Snake_Game::SelectStage()
{
	snake_ = new Snake();

	Map* stage_one = new Map(STAGE_ONE,"Stage1.txt");
	Map* stage_two = new Map(STAGE_TWO,"Stage2.txt");
	Map* stage_three = new Map(STAGE_THREE,"Stage3.txt");
	Map* stage_four = new Map(STAGE_FOUR,"Stage4.txt");

	MAP_MANAGER->RegisterMap(stage_one);
	MAP_MANAGER->RegisterMap(stage_two);
	MAP_MANAGER->RegisterMap(stage_three);
	MAP_MANAGER->RegisterMap(stage_four);

	while(true)
	{
		this->InitGame();

		//UI를 위해서
		MoveCursor(Position(14,21));
		puts("N = 다음 스테이지 / P = 이전 스테이지 / S = 시작");

		int ch=getch();

		//키값을 받고, N이면 다음스테이지 P면 이전스테이지 S를 누르면 루프를빠져간다.
		if (ch == 0xE0) 
		{
			getch();
		} 
		else 
		{
			if (tolower(ch) == 'n') 
			{
				if(current_stage_ < STAGE_FOUR)
				{
					current_stage_++;
				}
			}
			if (tolower(ch) == 'p') 
			{
				if(current_stage_ > STAGE_ONE)
				{
					current_stage_--;
				}
			}
			if (tolower(ch) == 's')
			{
				break;
			}
		}
	}

	//UI를 지우기위해,/
	MoveCursor(Position(14,21));
	puts("                                                 ");
}

//------------------------------- InitGame ------------------------------------
// 게임을 초기화한다.
//-----------------------------------------------------------------------------
bool Snake_Game::InitGame()
{
	SetCursorType(NOCURSOR);

	system("cls");

	snake_ = new Snake();

	switch(current_stage_)
	{
	case STAGE_ONE:
		{
			speed_ = 150;
			goal_item_num_ = 10;
			snake_->InitSnake();
		}
		break;
	case STAGE_TWO:
		{
			speed_ = 100;
			goal_item_num_ = 15;
			snake_->InitSnake();
		}
		break;
	case STAGE_THREE:
		{
			speed_ = 80;
			goal_item_num_ = 20;
			snake_->InitSnake();
		}
		break;
	case STAGE_FOUR:
		{
			speed_ = 50;
			goal_item_num_ = 25;
			snake_->InitSnake();
		}
		break;
	}

	MAP_MANAGER->GetMapFromID(current_stage_)->LoadMap();

	srand((unsigned)time(NULL));

	//남은 아이템만큼 아이템을 그려준다.
	for (int i=snake_->GetEatItemCounter();i<goal_item_num_;i++)
	{
		while(true)
		{
			Position dummy(rand()%kMaxItemPosWidth,rand()%kMaxItemPosHeigh);
			if(Getchon(dummy) == ' ')
			{
				DrawObject(dummy,rand()%9+1);
				break;
			}
		}
	}

	this->DrawUI();

	return true;
}

//-------------------------------- Input --------------------------------------
// 사용자의 입력값을 처리해주는 함수
//-----------------------------------------------------------------------------
void Snake_Game::Input()
{
	int ch;

	if (!kbhit()) {
		return;
	}

	ch=getch();

	//뱀은 현재 진행방향의 반대방향으로는 움직이지 못한다.
	//스페이스를 누르면 멈출수 있다.
	if (ch == 0xE0 || ch == 0) 
	{
		ch=getch();
		snake_->Input(ch);
	}
	else
	{
		switch (tolower(ch))
		{
		case 27:
			SetCursorType(NORMALCURSOR);
			exit(0);
		case ' ':
			WaitAnyKey();
			break;
		}
	}
}

//-------------------------------- Update -------------------------------------
// 로직
//-----------------------------------------------------------------------------
void Snake_Game::Update()
{
	//사용자의 입력을 받는다.
	this->Input();

	//뱀의 움직임을 업데이트한다.
	snake_->Update();


	Sleep(this->speed_);
}

//-------------------------------- IsGameOver ---------------------------------
// 해당조건에 따라 게임을 종료한다.
//-----------------------------------------------------------------------------
bool Snake_Game::IsGameOver()
{

	if(!snake_->IsActive())
	{
		if(--life_ < 0)
		{
			MoveCursor(Position(18,20));
			puts("게임이 끝났습니다. 그만 놀고 열심히 공부하세요.");
			WaitAnyKey();
			return true;
		}
		else
		{
			this->InitGame();
			Sleep(500);
		}
	}

	if(snake_->GetEatItemCounter() == goal_item_num_)
	{
		if(current_stage_ < STAGE_MAX - 1)
		{
			current_stage_++;
			MoveCursor(Position(12,20));
			puts("축하합니다. 아무 키나 누르시면 다음 스테이지로 갑니다.");
			WaitAnyKey();
			this->InitGame();
			Sleep(500);
		}
		else
		{
			MoveCursor(Position(18,20));
			puts("모든 스테이지를 끝내셨습니다. 수고하셨습니다.");
			WaitAnyKey();
			return true;
		}
	}

	return false;
}

//-------------------------------- Render -------------------------------------
// 렌더함수
//-----------------------------------------------------------------------------
void Snake_Game::Render()
{
	//UI를 그린다.
	this->DrawUI();
	snake_->Render();
}

//--------------------------------- Run ---------------------------------------
// 루프
//-----------------------------------------------------------------------------
void Snake_Game::Run()
{
	this->SelectStage();

	while(!this->IsGameOver())
	{
		Update();
		Render();
	}
}

//--------------------------------- DrawUI ------------------------------------
// UI를 그린다.
//-----------------------------------------------------------------------------
void Snake_Game::DrawUI()
{
	MoveCursor(Position(0,23));printf("스테이지 : %d",current_stage_+1);
	MoveCursor(Position(20,23));printf("남은 뱀 : %d", life_);
	MoveCursor(Position(40,23));printf("              ");
	MoveCursor(Position(40,23));printf("남은 먹이 : %d",goal_item_num_ - snake_->GetEatItemCounter());
	MoveCursor(Position(60,23));printf("꼬리 길이 : %d",snake_->GetLength());
}

//--------------------------------- ~Snake_Game -------------------------------
// 소멸자
//-----------------------------------------------------------------------------
Snake_Game::~Snake_Game()
{
	MAP_MANAGER->Destory();
	delete snake_;
}